package program.services;

import program.domain.PCB;
import program.utils.PCBQueue;
import java.util.ArrayList;


/**
 * The type First come first served.
 *
 * @program: OSAlgorithms
 * @description: 先来先服务算法
 * @author: W
 * @create: 2021 -10-20 13:30
 */
public class FirstComeFirstServed {
    /**
     * 当前时间
     */
    private int time = 0;

    /**
     * The Ready queue.
     */
    public PCBQueue readyQueue = new PCBQueue();

    /**
     * The Running queue.
     */
    public PCBQueue runningQueue = new PCBQueue();

    /**
     * The Finished queue.
     */
    public PCBQueue finishedQueue = new PCBQueue();

    /**
     * The Processes.
     */
    public ArrayList<PCB> processes = new ArrayList<>();

    /**
     * Gets time.
     *
     * @return the time
     */
    public int getTime() {
        return time;
    }

    /**
     * Sets time.
     *
     * @param time the time
     */
    public void setTime(int time) {
        this.time = time;
    }

    /**
     * Gets ready queue.
     *
     * @return the ready queue
     */
    public PCBQueue getReadyQueue() {
        return readyQueue;
    }

    /**
     * Sets ready queue.
     *
     * @param readyQueue the ready queue
     */
    public void setReadyQueue(PCBQueue readyQueue) {
        this.readyQueue = readyQueue;
    }

    /**
     * Gets running queue.
     *
     * @return the running queue
     */
    public PCBQueue getRunningQueue() {
        return runningQueue;
    }

    /**
     * Sets running queue.
     *
     * @param runningQueue the running queue
     */
    public void setRunningQueue(PCBQueue runningQueue) {
        this.runningQueue = runningQueue;
    }

    /**
     * Gets finished queue.
     *
     * @return the finished queue
     */
    public PCBQueue getFinishedQueue() {
        return finishedQueue;
    }

    /**
     * Sets finished queue.
     *
     * @param finishedQueue the finished queue
     */
    public void setFinishedQueue(PCBQueue finishedQueue) {
        this.finishedQueue = finishedQueue;
    }

    /**
     * Gets processes.
     *
     * @return the processes
     */
    public ArrayList<PCB> getProcesses() {
        return processes;
    }

    /**
     * Sets processes.
     *
     * @param processes the processes
     */
    public void setProcesses(ArrayList<PCB> processes) {
        this.processes = processes;
    }

    /**
     * Scheduling.
     */
    public void scheduling() {

        while (!readyQueue.isEmpty()) {
            if (runningQueue.peek() == null) {
                //就绪队列有进程，且运行队列空闲

                //出队
                PCB process = readyQueue.remove();

                runningQueue.add(process);
                process.setState("运行");

                try {
                    //模拟cpu执行进程
                    System.out.println("进程" + process.getPid() + "开始执行");
                    Thread.sleep(process.getCpuTime());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("进程" + process.getPid() + "已执行完毕，耗时：" + process.getCpuTime() + "ms");
                PCB pcb = runningQueue.remove();
                pcb.setState("结束");
                finishedQueue.add(pcb);

            }
        }

        System.out.println("全部进程执行完毕");

    }

    /**
     * 调度准备队列
     */
    public void scheduleReady() {
        if (!processes.isEmpty()) {
            while (processes.get(0).getArriveTime() <= time) {
                PCB pcb = processes.get(0);
                pcb.setState("就绪");
                readyQueue.add(pcb);
                System.out.println("进程" + pcb.getPid() + "进入就绪队列");
                processes.remove(0);
                if (processes.size()==0){
                    break;
                }
            }
        }
    }

    /**
     * 调度运行队列
     */
    public void scheduleRunning() {
        time += 1;
        if (runningQueue.isEmpty()&&readyQueue.peek()!=null) {
            //cpu空闲
            PCB pcb = readyQueue.remove();
            pcb.setState("运行");
            System.out.println("进程" + pcb.getPid() + "开始执行");
            runningQueue.add(pcb);
        }

    }

    /**
     * 进程运行
     */
    public void processRunning(){
        if (!runningQueue.isEmpty()) {
            //cpu执行进程中,改变剩余时间
            PCB pcb = runningQueue.peek();
            int needTime = pcb.getNeedTime() - 1;
            pcb.setNeedTime(needTime);
            pcb.setCount(1);
            if (pcb.getNeedTime() == 0) {
                //运行结束
                runningQueue.remove();
                pcb.setState("结束");
                System.out.println("进程" + pcb.getPid() + "已执行完毕，耗时：" + pcb.getCpuTime() + "ms");
                finishedQueue.add(pcb);
            }
        }
    }

}
